﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace ElectronicCommerce.Framework.Caching.DoubleCacheProvider
{
    /// <summary>
    /// Double Cache Collection
    /// </summary>
    internal class DoubleCacheCollection
    {
        #region Properties

        protected static Dictionary<string, DoubleCacheItem> store;

        protected static Dictionary<string, DoubleCacheItem> Store
        {
            get
            {
                if (store == null)
                {
                    store = new Dictionary<string, DoubleCacheItem>();
                }
                return store;
            }
        }

        #endregion

        #region Methods

        public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
        {
            foreach (var item in Store)
            {
                yield return new KeyValuePair<string, object>(item.Key, item.Value.DisplayCacheItem);
            }
        }

        public void Clear()
        {
            Store.Clear();
        }

        public bool Remove(KeyValuePair<string, object> item)
        {
            return Remove(item.Key);
        }

        public int Count
        {
            get { return Store.Count; }
        }

        public bool ContainsKey(string key)
        {
            return Store.ContainsKey(key);
        }

        public void Add(string key, object value)
        {
            Add(key, string.Empty, value);
        }

        public void Add(string key, string path, object value)
        {
            Add(key, path, value, null);
        }

        public void Add(string key, object value, Func<object> callbackFunc)
        {
            Add(key, string.Empty, value, callbackFunc);
        }

        private void Add(string key, string path, object value, Func<object> callbackFunc)
        {
            DoubleCacheItem item = !ContainsKey(key) ?
                new DoubleCacheItem() : Store[key];
            if (item.IsUpdating)
            {
                return;
            }
            item.FilePath = path ?? string.Empty;
            item.CacheItem = value;
            item.DisplayCacheItem = value;
            item.CallbackFunc = callbackFunc;
            if (!ContainsKey(key))
            {
                Store.Add(key, item);
            }
        }

        public bool Remove(string key)
        {
            if (ContainsKey(key))
            {
                return Store.Remove(key);
            }
            return false;
        }

        public bool TryGetValue(string key, out object value)
        {
            value = null;
            if (ContainsKey(key))
            {
                value = Store[key].DisplayCacheItem;
                return true;
            }
            return false;
        }

        public object this[string key]
        {
            get
            {
                object value;
                TryGetValue(key, out value);
                return value;
            }
            set
            {
                Add(key, value);
            }
        }

        public ICollection<string> Keys
        {
            get
            {
                return Store.Select(c => c.Key).ToList();
            }
        }

        public ICollection<object> Values
        {
            get { return Store.Select(c => c.Value.CacheItem).ToList(); }
        }

        #endregion


        #region Call back method

        internal static DoubleCacheItem GetItem(string key)
        {
            return Store[key];
        }

        #endregion
    }
}
